﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace OperationPlugins.Validators
{
    /// <summary>
    /// Used to identify the validation level and the target types for validation.
    /// </summary>
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
    public sealed class ValidatorOfAttribute : Attribute
    {
        private bool _inherited = true;
        private readonly ValidationLevel _level;
        private readonly List<Type> _targetTypes = new List<Type>();

        /// <summary>
        /// Initializes a new instance of the ValidatorOfAttribute class.
        /// </summary>
        /// <param name="level">Validation level</param>
        /// <param name="targetType">Target type</param>
        /// <param name="otherTargetTypes">Other target types</param>
        public ValidatorOfAttribute(ValidationLevel level, Type targetType, params Type[] otherTargetTypes)
        {
            if (targetType == null)
            {
                throw new ArgumentNullException("targetType");
            }

            if (otherTargetTypes == null)
            {
                throw new ArgumentNullException("otherTargetTypes");
            }

            if (otherTargetTypes.Any(x => x == null))
            {
                throw new ArgumentNullException("otherTargetTypes");
            }

            _level = level;

            _targetTypes.Add(targetType);

            foreach (Type otherTargetType in otherTargetTypes.Where(otherTargetType => _targetTypes.Contains(otherTargetType) == false))
            {
                _targetTypes.Add(otherTargetType);
            }
        }

        /// <summary>
        /// Gets or sets a Boolean value indicating whether inherited types are also accepted. 
        /// </summary>
        public bool Inherited
        {
            set { _inherited = value; }
            get { return _inherited; }
        }

        /// <summary>
        /// Gets all target types.
        /// </summary>
        public IEnumerable<Type> TargetTypes
        {
            get { return _targetTypes.AsEnumerable(); }
        }

        /// <summary>
        /// Get the validation level.
        /// </summary>
        public ValidationLevel ValidationLevel
        {
            get { return _level; }
        }
    }
}